package helixoide.secondlife.devices;

import java.util.ArrayList;
import helixoide.Config;
import helixoide.Util;
import helixoide.backupThread;
import helixoide.hxLog;
import helixoide.users.UserManager;

/*
 * This class manages each communications device in sl
 * It also routes its messages to the approiate places backupThread
 */
public class deviceManager 
{
	private UserManager theManagment;
	private ArrayList<device> deviceList = new ArrayList<device>();
	private Config serverConfig;
	private ArrayList<String> channelsUsed = new ArrayList<String>();
	private final double pingTimeOut = (300000);//ping time out is 5min if the System.currentTimeMillis(); - device.getLastPing() > pingTimeOut remove it
	private final int pingCheckLimit = 5;//after 5 checkIns we start a thread to check all devices to see if they have timedOut
	private int currentPingCheck = 0;//used to count how many checks we have done when we reach pingCheckLimit we run a thread to 
	public deviceManager(UserManager managment, Config serverConfig)
	{
		this.serverConfig = serverConfig;
		this.theManagment = managment;
	}
	
	public device[] getDevices()
	{
		device[] blah = new device[this.deviceList.size()];
		this.deviceList.toArray(blah);
		return blah;
	}
	public synchronized device findDevice(String uuid)
	{
		device[] listOfDevices = this.getDevices();
		device toReturn = null;
		for(int i = 0;i<listOfDevices.length;i++)
		{
			if(listOfDevices[i]!=null)
			{
				
				if(listOfDevices[i].getUUID().equals(uuid))
				{
					
					toReturn = listOfDevices[i];
					break;
				}
			}
		}
		return toReturn;
	}
	
	public synchronized void register(String uuid, String location, String region, String channel, String url, boolean fromBackup)//registration section used to register devices
	{
		/*
		 * We need to check that this device is not already registered
		 * TODO: implement a check for channel passwords so we don't get unauthorized people connecting to a channel we don't want them to connect to
		 * We also need to add a check for channels to make sure we don't connect multiple devices to the same channel
		 */
		device theDevice = this.findDevice(uuid);
		if(theDevice!=null)
		{
			
			if(theDevice.getURL().equals(url))
			{
				//this device already exists
				
				hxLog.write("DeviceManager", "A Device has tried to register twice 0.0");
			}
			if(!theDevice.getURL().equals(url))
			{
				
				theDevice.updateURL(url);
			}
		}
		else
		{
			if(!this.channelsUsed.contains(channel))
			{ 
				//new device registered!
				//(String url, String uuid, String region, String location, String channel, UserManager managment)
				device temp = new device(url, uuid, region, location, channel, theManagment,this.serverConfig,this);
				deviceList.add(temp);
				this.channelsUsed.add(channel);
				hxLog.write("DeviceManager", "New Device is registering with sever!\n------> " + temp.getUUID() + " " + location + " " + temp.getChannel() + " " + temp.getURL() +"\n");
				//we have successfully added a new device!
			}
			else
			{
				hxLog.write("DeviceManager","Extra device tried to register with channel " + channel + " device info: " + region + " " + location);
			}
		}
		if(!fromBackup)//make sure we don't go backing up what we already have (right after we load)
		{
			//this is where we back stuff up and conduct other such shananigans such as dealing with pings
			if(theDevice != null)
			{
				
				double reference = System.currentTimeMillis();
				theDevice.updatePing(reference);//use this as our standard time for this update
				// this next bit is for Selig: She required some location shit so i am putting this in. She quickly changed her mind but i am going leave it in just because
				theDevice.updateLocation(location, region);
				this.currentPingCheck++;
				if(this.currentPingCheck >=this.pingCheckLimit)
				{
					hxLog.write("DeviceManager","Starting Ping check");
					//time to check our pings
					device[] toCheck = this.getDevices();
					for(int i = 0;i<toCheck.length;i++)
					{
						hxLog.write("PingCheck", "Ping for device on channel " + toCheck[i].getChannel() + " difference of " + (reference - toCheck[i].getlastPing()));
						if((reference - toCheck[i].getlastPing()) > this.pingTimeOut)//check to see if we exceed the time
						{
							toCheck[i].delete("Device timed out");
						}
					}
					this.currentPingCheck = 0;
				}
				
			}
			Util.startThread((new Thread(new backupThread(this))), "Backup Thread");
		}
	}
	public void removeDeviceFromList(int index)
	{
		this.deviceList.remove(index);
		
	}
	public void removeDeviceFromList(device d)
	{
		System.out.println(this.deviceList.remove(d));
	}
	//handler for incomming messages
	public void handle(String incoming)
	{
		
		String[] step1 = incoming.split("<<",2);//Separate the body from the ident
		
		if(step1[0].equals("non-queued"))
		{
			
			Util.startThread(new Thread(new deviceHandlerThread(this,step1[1])),"deviceHandlerThread.java");
		}
		if(step1[0].equals("queued"))
		{
			String[] step2 = step1[1].split(":*:");//Separate each of the queued messages
			for(int i = 0;i<step2.length;i++)
			{
				
				Util.startThread(new Thread(new deviceHandlerThread(this,step2[i])), "deviceHandlerThread.java");
				
			}
		}
		//YAY as of 10:52pm on Saturday January 16 2010 
		//I Ross Delinger have completed the first revision of the command structure for SLServ
		
		
	}

}
